---
title: Elements & JSX
description: "Basic concepts for React elements and how to use them in JSX"
canonical: "/docs/react/elements-and-jsx"
section: "Main Concepts"
order: 1
---

# Elements & JSX

<Intro>

Elements are the smallest building blocks of React apps. This page will explain how to handle `React.element`s in your React app with our dedicated JSX syntax.

</Intro>

> **Note:** The output shown for the examples on this page assumes your `rescript.json` to be set to `"jsx": { "version": 4, "mode": "classic" }`. We will update it for automatic mode soon.

## Element Basics

Let's start out by creating our first React element.

```res example
let element = <h1> {React.string("Hello World")} </h1>
```

The binding `element` and the expression `{React.string("Hello World")}` are both of type `React.element`, the fundamental type for representing React elements within a React application. An element describes what you see on the screen whenever you render your application to the DOM.

Let's say you want to create a function that handles another React element, such as `children`, you can annotate it as `React.element`:

```res example
let wrapChildren = (children: React.element) => {
  <div>
    <h1> {React.string("Overview")} </h1>
    children
  </div>
}

wrapChildren(<div> {React.string("Let's use React with ReScript")} </div>)
```

Understanding the definition of a `React.element` is essential since it is heavily used within the React APIs, such as `ReactDOM.Client.Root.render(..., element)`, etc. Be aware that JSX doesn't do any automatic `string` to `React.element` conversion for you (ReScript forces explicit type conversion). For example `<div> Hello World </div>` will not type-check (which is actually a good thing because it's also a huge source for subtle bugs!), you need to convert your `"Hello World"` with the `React.string` function first.

Fortunately our React bindings bring all necessary functionality to represent all relevant data types as `React.element`s.

## Using Elements within JSX

You can compose elements into more complex structures by using JSX:

```res example
let greeting = React.string("Hello ")
let name = React.string("Stranger")


// element is also of type React.element
let element = <div className="myElement"> greeting name </div>
```

JSX is the main way to express your React application as a tree of elements.

Sometimes, when doing a lot of interop with existing ReactJS codebases, you'll find yourself in a situation where you can't use JSX syntax due to syntactic restrictions. For a more detailed description of how those functions work, please refer to the [JSX](../manual/jsx.mdx) documentation.

## Creating Elements

### Creating Elements from `string`, `int`, `float`, `array`

Apart from using JSX to create our React elements or React components, the `React` module offers various functions to create elements from primitive data types:

```res example
React.string("Hello") // new element representing "Hello"

React.int(1) // new element representing "1"

React.float(1.0) // new element representing "1.0"
```

It also offers `React.array` to represent multiple elements as one single element (useful for rendering a list of data, or passing children):

```res example
let element = React.array([
  React.string("element 1"),
  React.string("element 2"),
  React.string("element 3")
])
```

**Note:** We don't offer a `React.list` function because a `list` value would impose runtime overhead. ReScript cares about clean, idiomatic JS output. If you want to transform a `list` of elements to a single React element, combine the output of `Belt.List.toArray` with `React.array` instead.

### Creating Null Elements

ReScript doesn't allow `element || null` constraints due to it's strongly typed nature. Whenever you are expressing conditionals where a value might, or might not be rendered, you will need the `React.null` constant to represent _Nothingness_:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let name = Some("Andrea")

let element = switch name {
  | Some(name) => <div> {React.string("Hello " ++ name)} </div>
  | None => React.null
}

<div> element </div>
```

```js
var name = "Andrea";

var element =
  name !== undefined
    ? React.createElement("div", undefined, "Hello " + name)
    : null;

React.createElement("div", undefined, element);
```

</CodeTab>

## Escape Hatches

**Note:** This chapter features low level APIs that are used by JSX itself, and should only be used whenever you hit certain JSX syntax limitations. More infos on the JSX internals can be found in our [Beyond JSX](./beyond-jsx.mdx) section.

### Creating Elements from Component Functions

**Note:** To learn about the details on creating components, please look at the [Components and Props](./components-and-props.mdx) section.

Sometimes it's necessary to pass around component functions to have more control over `React.element` creation. Use the `React.createElement` function to instantiate your elements:

```res example
type props = {name: string}

let render = (myComp: props => React.element) => {
  <div> {React.createElement(myComp, {name: "Franz"})} </div>
}
```

This feature is often used when interacting with existing JS / ReactJS code. In pure ReScript React applications, you would rather pass a function that does the rendering for you (also called a "render prop"):

```res example
let render = (renderMyComp: (~name: string) => React.element) => {
  <div> {renderMyComp(~name="Franz")} </div>
}
```

#### Pass Variadic Children

There is also a `React.createElementVariadic` function, which takes an array of children as a third parameter:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
type props = {title: string, children: React.element}

let render = (article: props => React.element) => {
  let children = [React.string("Introduction"), React.string("Body")]

  let props = {title: "Article #1", children: React.null}

  {React.createElementVariadic(article, props, children)}
}
```

```js
function render(article) {
  var children = ["Introduction", "Body"];
  var props = {
    title: "Article #1",
    children: null,
  };
  return Caml_splice_call.spliceApply(React.createElement, [
    article,
    props,
    children,
  ]);
}
```

</CodeTab>

**Note:** Here we are passing a prop `"children": React.null` to satisfy the type checker. React will ignore the children prop in favor of the children array.

This function is mostly used by our JSX transformations, so usually you want to use `React.createElement` and pass a children prop instead.

### Creating DOM Elements

To create DOM elements (`<div>`, `<span>`, etc.), use `ReactDOM.createDOMElementVariadic`:

```res example
ReactDOM.createDOMElementVariadic("div", ~props={className: "card"}, [])
```

ReScript can make sure that we are only passing valid dom props. You can find an exhaustive list of all available props in the [JsxDOM](https://github.com/rescript-lang/rescript/blob/3bc159f33a3534280bbc26be88fa37ea2114dafe/jscomp/others/jsxDOM.res#L31) module.

### Cloning Elements

**Note:** This is an escape hatch feature and will only be useful for interoping with existing JS code / libraries.

Sometimes it's required to clone an existing element to set, overwrite or add prop values to a new instance, or if you want to set invalid prop names such as `data-name`. You can use `React.cloneElement` for that:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
let original = <div className="hello"/>

// Will return a new React.element with className set to "world"
React.cloneElement(original, {"className": "world", "data-name": "some name"})
```

```js
var original = React.createElement("div", {
  className: "hello",
});

React.cloneElement(original, {
  className: "world",
  "data-name": "some name",
});
```

</CodeTab>

The feature mentioned above could also replicate `props spreading`, a practise commonly used in ReactJS codebases, but we strongly discourage the usage due to its unsafe nature and its incorrectness (e.g. adding undefined extra props to a component doesn't make sense, and causes hard to find bugs).

In ReScript, we rather pass down required props explicitly to leaf components or use a renderProp instead. We introduced [JSX punning](../manual/jsx.mdx#punning) syntax to make the process of passing down props more convenient.
